package project_package;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class SalesRecords {

	private static SalesRecords instance = null;
	private HashMap<Integer, Sales> sales = new HashMap<Integer, Sales>();
	private ProductRecords productRecords; // not in diagram
	private int sellIndex = 0;

	public SalesRecords()
	{
		sellIndex = 0;
		productRecords = new ProductRecords();
	}

	public static SalesRecords getInstance()
	{
		if(instance == null)
		{
			instance = new SalesRecords();
		}
		return instance;
	}

	// add a sale to the list
	public void addSaleRecord(int id, Sales sale)
	{
		if(sale != null)
		{
			this.sales.put(id, sale);
			//System.out.println("Sale was added successfully");
		}	
	}

	// delete a sale from the list
	public void deleteSaleRecord(Sales sale)
	{
		Set<Map.Entry<Integer, Sales>> st = sales.entrySet();
    	for(Map.Entry<Integer, Sales> item : st)
		{
			if (item.getValue().equals(sale))
			{
				sales.remove(item.getKey());
			}
		}
	}

	// search for sale
	public Sales searchSaleRecord(int id)
	{
		if (!sales.isEmpty())
		{
			Set<Map.Entry<Integer, Sales>> st = sales.entrySet();
	    	for(Map.Entry<Integer, Sales> item : st)
			{
				if (item.getKey() == id)
				{
					return item.getValue();
				}
			}
		}
		return null;
	}

	// confirm a sell (type of payment). sale is no longer editable, goods can be taken, it is still not paid
	public void confirmSale(Sales sale, boolean isCash) 
	{
		sale.setIsConfirmed(true);
		sale.setIsCash(isCash);
		//System.out.println("Sale #"+sale.getID()+" is now confirmed. Payment method: " + (isCash ? "cash" : "debit card"));
	}

	// print sale info
	public void printSaleInfo(Sales sale)
	{
		ArrayList<SalesLineItem> line = sale.getProductList();
		double price = 0.0;
		double discount = sale.getCustomer().getDiscount();
		for (SalesLineItem info : line) {
			Product product = info.getProduct();
			price += product.getPriceDiscount()*info.getQuantity();
			System.out.println("Product: "+product.getName()+" -- Price: "+product.getPriceDiscount()+"("+product.getPrice()+") -- Quantity: "+info.getQuantity()+" -- Total Price: "+product.getPriceDiscount()*info.getQuantity()+"");
		}
		System.out.println("Price: "+price);
		System.out.println("Customer discount: -"+price*discount+" DKK "+discount*100+"%");
		System.out.println("Total Price: "+(price-(price*discount)));
	}

	// initializes new sale
	public int createSaleRecord(Customer customer, Employee employee)
	{
		sellIndex++;
		Sales newSale = new Sales(sellIndex, customer, employee);
		addSaleRecord(sellIndex, newSale);
		return sellIndex;
	}

	// add a product to cart	
	public boolean addProductToCart(Sales sale, Product product, int quantity)
	{
		int productAvailable = productRecords.getQuantity(product);
		ArrayList<SalesLineItem> line = sale.getProductList();	 // we get the arraylist of current items of the sale object

		if(productAvailable < quantity)
		{
			//System.out.println("Requested quantity exceeds current stock");
			return false;
		} 
		else {
			if(isProductInCart(line, product))  {	
				//updateProductFromCart(sale, product, (getProductQuantityInLine(line, product) + quantity));
				return false;
			}
			else {
				SalesLineItem newItem = new SalesLineItem(product, quantity); // we create a new SalesLineItem object

				line.add(newItem); 	// we add the new SalesLineItem object which contains the new product and quantity
				productRecords.changeProductQuantity(product, (productAvailable-quantity));	// remove from product list

				return true;
			}
		}
	}

	public ArrayList<SalesLineItem> getProductList(Sales sale)
	{
		return sale.getProductList();
	}

	public boolean isProductInCart(ArrayList<SalesLineItem> salesLine, Product product) 
	{
		boolean found = false;
		Iterator<SalesLineItem> it = salesLine.iterator();
		while(it.hasNext())
		{
			SalesLineItem p = it.next();
			if (p.getProduct().equals(product)) {
				found = true;
			}
		}
		return found;
	}
	
	public int getProductQuantityInLine(ArrayList<SalesLineItem> salesLine, Product product) 
	{
		int quantity = 0;
		Iterator<SalesLineItem> it = salesLine.iterator();
		while(it.hasNext())
		{
			SalesLineItem p = it.next();
			if (p.getProduct().equals(product)) {
				quantity = p.getQuantity();
			}
		}
		return quantity;
	}

	// remove product from cart
	public boolean deleteProductFromCart(Sales sale, Product product) 
	{
		int productAvailable = productRecords.getQuantity(product);
		ArrayList<SalesLineItem> line = sale.getProductList();
		for (SalesLineItem item : line)
		{
			if (item.getProduct().equals(product)) {
				productRecords.changeProductQuantity(product, (productAvailable+item.getQuantity()));
				line.remove(item);
				return true;
			}
		}
		return false;
	}

	// update product's quantity
	public boolean updateProductFromCart(Sales sale, Product product, int quantity) 
	{
		ArrayList<SalesLineItem> line = sale.getProductList(); 
		for (SalesLineItem item : line)
		{
			if (item.getProduct().equals(product))
			{ 
				int totalProducts = item.getQuantity() + productRecords.getQuantity(product); 
				if (totalProducts >= quantity) {
					productRecords.changeProductQuantity(product, (totalProducts-quantity));				
					item.setQuantity(quantity); 
					//System.out.println("Quantity changed to " + quantity + " on product " + product.getName());
					return true;
				}
				//else {
				//	System.out.println("Requested quantity exceeds current stock");						
				//}
			}
		}
		return false;
	}

	// empty shopping cart
	public void emptyProductCart(Sales sale) 
	{
		ArrayList<SalesLineItem> line = sale.getProductList(); // we get the arraylist of current items of the sale object
		for (int i = 0; i < line.size(); i++) { // we check each  row
			Product currentProduct = line.get(i).getProduct();
			int productAvailable = productRecords.getQuantity(currentProduct);
			productRecords.changeProductQuantity(currentProduct, (productAvailable+line.get(i).getQuantity()));
			line.remove(i); // we remove it
		}
		//sale.getProductList().clear(); // easy way to clear a sales' list, BUT we have to do a loop, to return all the stocks...
		//System.out.println("The shopping list has been cleared");
	}


	public HashMap<Integer, Sales> getAllSales()
	{
		return sales;
	}

	// get current sale price
	public double getSalePrice(int id)
	{
		if (sales.isEmpty()) {
			System.out.println("No sales in the database");
			return 0;
		}
		else {	
			for (int i = 0; i < sales.size(); i++) {
				if (sales.get(i).getID() == id) {
					return sales.get(i).getTotal();
				}
			}
		}
		System.out.println("Sale with ID #"+id+" was not found");
		return 0;
	}

	// gets all of the sales combined total price
	public double getTotalSalesPrice()
	{
		double totalSales = 0.0;
		Set<Map.Entry<Integer, Sales>> st = sales.entrySet();
    	for(Map.Entry<Integer, Sales> item : st)
		{
			totalSales += item.getValue().getTotal();
		}
		return totalSales;
	}

	// print all sales
	public void printSalesRecords()
	{
		Set<Map.Entry<Integer, Sales>> st = sales.entrySet();
    	for(Map.Entry<Integer, Sales> item : st)
		{
    		Sales sale = item.getValue();
			System.out.println("Sale #"+sale.getID()+" - Employee: "+sale.getEmployee().getName()+" - Customer: "+sale.getCustomer().getName()+" - Total Price: "+sale.getTotal()+" - Date: "+sale.getDate()+"");
		}
	}

	// gets total number of all sales
	public int getTotalSalesNumber() 
	{
		return sales.size();
	}

	// gets total number of all sales for the last month
	public int getTotalSalesLastMonth()
	{
		int i = 0;
		long datestamp = System.currentTimeMillis()/1000;

		Set<Map.Entry<Integer, Sales>> st = sales.entrySet();
    	for(Map.Entry<Integer, Sales> item : st)
		{
			// datestamp would result in such: 1355531028 (seconds elapsed since 1 Jan 1970 00:00:00)
			// we want to check for all the sales which happened last month
			// each month has approx 2592000 seconds (60s*60m*24h*30d)
			// if the current time minus one month (datestamp-1month) is less than 
			// the sale date, then it must be done in the last month
			if ((datestamp - 2592000) < item.getValue().getDateLong())
				i++;
		}

		return i;
	}

	// gets all of the sales combined total price from last month
	public double getTotalSalesPriceLastMonth()
	{
		double totalSales = 0.0;
		long datestamp = System.currentTimeMillis()/1000;

		Set<Map.Entry<Integer, Sales>> st = sales.entrySet();
    	for(Map.Entry<Integer, Sales> item : st)
		{
			// datestamp would result in such: 1355531028 (seconds elapsed since 1 Jan 1970 00:00:00)
			// we want to check for all the sales which happened last month
			// each month has approx 2592000 seconds (60s*60m*24h*30d)
			// if the current time minus one month (datestamp-1month) is less than 
			// the sale date, then it must be done in the last month
			if ((datestamp - 2592000) < item.getValue().getDateLong())
				totalSales += item.getValue().getTotal();
		}

		return totalSales;
	}
}